﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace XTeam.Core.Helper
{

    public partial class Dynamic
    {
        private static Dictionary<Type, IList<PropertyInfo>> _propertyCache = new Dictionary<Type, IList<PropertyInfo>>();

        public static object Eval(object obj, string bindPath)
        {
            Type sourceType = obj.GetType();
            IList<PropertyInfo> properties = null;

            if (!_propertyCache.TryGetValue(sourceType, out properties))
            {
                properties = sourceType.GetProperties();
                _propertyCache[sourceType] = properties;
            }
            if (properties == null || properties.Count < 1)
            {
                return null;
            }

            var t1 = Expression.Parameter(typeof(object));
            var getSource = Expression.Convert(t1, sourceType);

            string[] searchPath = bindPath.Split('.');

            object result = null;
            object source = obj;

            for (int i = 0; i < searchPath.Length; i++)
            {
                if (false)
                {
                    continue;
                }
                var property = Expression.Property(getSource, searchPath[i]);
                var convert = Expression.Convert(property, typeof(object));
                var fun = Expression.Lambda<Func<object, object>>(convert,
                new ParameterExpression[] { t1 }).Compile();
                result = fun(source);
                source = result;
                if (i < searchPath.Length)
                {
                    getSource = Expression.Convert(t1, result.GetType());
                }
            }
            return result;

        }
    }
}
